﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Revolio;
using System.Text.RegularExpressions;
using System.IO;

namespace RevolioReader
{
    public partial class BookListForm : Form
    {
        public BookListForm()
        {
            InitializeComponent();
        }

        private static string GetIssueOrder(string s)
        {
            s = s.ToUpperInvariant();
            Match m = new Regex(@"\d\d\d\d").Match(s);
            if (!m.Success)
                return s;

            int month = 0;
            switch (s.Substring(0, 3))
            {
                case "JAN": month = 1; break;
                case "FEB": month = 2; break;
                case "MAR": month = 3; break;
                case "APR": month = 4; break;
                case "MAY": month = 5; break;
                case "JUN": month = 6; break;
                case "JUL": month = 7; break;
                case "AUG": month = 8; break;
                case "SEP": month = 9; break;
                case "OCT": month = 10; break;
                case "NOV": month = 11; break;
                case "DEC": month = 12; break;

                case "SPR": month = 3; break;
                case "SUM": month = 6; break;
                case "AUT":
                case "FAL": month = 9; break;
                case "WIN": month = 12; break;
            }
            return string.Format("${0}${1:00}${2}", m.Groups[0].Value, month, s);
        }

        private void BookList_Load(object sender, EventArgs e)
        {
            // Load from XML.
            BookStore dir = null;
            try
            {
                using (Stream stream = File.OpenRead("BookStore.xml"))
                {
                    dir = BookStore.Load(stream);
                }
            }
            catch (Exception)
            {
                return;
            }

            //log = new ScanLog("scan.log");
            // txtStatus.Text = lvBooks.Items.Count + " books available.";
            // lvBooks_SelectedIndexChanged(lvBooks, null);

            SetWindowTheme(tvBooks.Handle, "explorer", null);

            var groups = from ent in // dir.GetTag(".Available").Books
                                     dir.Books
                         //where ent.Availability == BookAvailability.Available
                         group ent by ent.Title into g
                         orderby g.Key.ToLowerInvariant()
                         select g;
            foreach (var g in groups)
            {
                var issues = (from ent in g
                              orderby GetIssueOrder(ent.SubTitle)
                              select ent).ToArray();
                TreeNode root = tvBooks.Nodes.Add(g.Key + " (" + issues.Length + ")");
#if false
                if (issues.Length == 1) // only one issue
                {
                    root.Text += string.Format(" - {0} ({1})",
                        issues[0].SubTitle, issues[0].PageCount);
                }
                else
#endif
                {
                    foreach (var ent in issues)
                    {
                        TreeNode node = new TreeNode();
                        node.Text = string.Format("{0} ({1})", ent.SubTitle, ent.PageCount);
                        node.ToolTipText = string.Format("ID: {0}", ent.Id);
                        node.Tag = ent.Id;
                        root.Nodes.Add(node);
                    }
                }
            }

            // Update UI.
            tvBooks_AfterSelect(tvBooks, null);
        }

        [DllImport("uxtheme", CharSet = CharSet.Unicode)]
        public extern static int SetWindowTheme(IntPtr hWnd, string textSubAppName, string textSubIdList);

        private void btnUpdate_Click(object sender, EventArgs e)
        {
#if false
            // Convert ScanLog to BookDirectory.
            ScanLog log = new ScanLog("scan.log");

            BookStore store = new BookStore();
            foreach (ScanLogEntry se in log.Entries)
            {
                if (se.Message != null && se.Message != "")
                {
                    int kk = 1;
                }
                if (se.Availability == BookAvailability.Available)
                {
                    BookEntry be = new BookEntry();
                    be.Id = se.Id;
                    be.Title = se.Title;
                    be.SubTitle = se.SubTitle;
                    be.PageCount = se.PageCount;
                    //be.Message = (se.Message == "") ? null : se.Message;
                    store.Books.Add(be);
                }

                string tagName = "." + se.Availability.ToString();
                store.CreateTag(tagName).BookIds.Add(se.Id);
            }

            using (var stream = File.Create("BookStore.xml"))
            {
                store.Save(stream);
            }
#endif
            return;

#if false
            if (!btnUpdate.Enabled)
            {
                // btnRefresh.Checked = false;
                // cancel job
                return;
            }

            // Set button to checked status.
            btnUpdate.Enabled = false;

            // Try retrieve the meta data of all book IDs.
            for (int id = 1; ; id++)
            {
                ScanLogEntry ent = log.GetEntry(id);
                if (ent != null && ent.Availability != BookAvailability.Unknown)
                    continue;

                //txtStatus.Text = "Checking book " + id + "...";

                ent = new ScanLogEntry();
                ent.Id = id;
                try
                {
                    Book b = await Task<Book>.Factory.StartNew(() => Book.Load(id));
                    ent.Availability = b.Availability;
                    if (b.Availability == BookAvailability.Available)
                    {
                        ent.Title = b.Title;
                        ent.SubTitle = b.Issue;
                        ent.PageCount = b.PageCount;
                        // DisplayLogEntry(ent);
                    }
                }
                catch (Exception ex)
                {
                    ent.Availability = BookAvailability.Unknown;
                    ent.Message = ex.Message;
                    throw ex;
                }
                log.AddEntry(ent);
            }
#endif
        }

        private async void btnProperties_Click(object sender, EventArgs e)
        {
            // Note: This must not be async, otherwise we'll have too many
            // modal dialog boxes.
            int id = this.SelectedId;
            if (id == 0)
                return;
            Book book = await Task<Book>.Factory.StartNew(() => Book.Load(id));
            PropertiesForm f = new PropertiesForm();
            f.SelectedObject = book;
            f.ShowDialog(this);
        }

        public int SelectedId
        {
            get
            {
                if (tvBooks.SelectedNode != null && tvBooks.SelectedNode.Tag != null)
                    return (int)tvBooks.SelectedNode.Tag;
                else
                    return 0;
            }
        }

        private void btnAddBook_Click(object sender, EventArgs e)
        {
            AddBookForm f = new AddBookForm();
            f.ShowDialog(this);
        }

        private void btnRemoveBook_Click(object sender, EventArgs e)
        {

        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            if (this.SelectedId > 0)
            {
                this.DialogResult = DialogResult.OK;
                this.Close();
            }
        }

        private void tvBooks_AfterSelect(object sender, TreeViewEventArgs e)
        {
            bool ok = (tvBooks.SelectedNode != null && tvBooks.SelectedNode.Tag != null);
            btnRemoveBook.Enabled = ok;
            btnProperties.Enabled = ok;
            btnOK.Enabled = ok;
        }

        private void tvBooks_DoubleClick(object sender, EventArgs e)
        {
            btnOK_Click(btnOK, null);
        }
    }
}
